module Jqgrid
  def find_by_params(params, opts)
    clase = opts[:class]
    page  = params[:page] ? (params[:page]).to_i : 1
    rp    = params[:rows] ? (params[:rows]).to_i : 10
    sortname  = params[:sidx] 
    sortorder = params[:sord] ? params[:sord] : "desc"
    tipo = opts[:tipo_join] ? opts[:tipo_join] : :joins
    condiciones = []
    incluir = opts[:includes] ? opts[:includes] : []
    start = ((page-1) * rp).to_i
    where = []
    parametros = []
    #Realizar busqueda?
    if params["_search"] == "true"
      #Determinar si la busqueda es sencilla o compleja
      if params[:filters] and !params[:filters].empty? #compleja
        #variables locales
        cond = ActiveSupport::JSON.decode(params[:filters])
        #recorrer reglas compuestas
        cond["rules"].each do |rule|
          n_where, n_param = parse_params(rule["field"], rule["op"], rule["data"])
          where << n_where
          parametros  << n_param
        end
        n_where,n_param=get_condiciones_sencillas(params)
        where << n_where unless n_where.empty?
        parametros  = parametros + n_param
        union =  (parametros.count>1) ? cond["groupOp"] : ""
      else #sencilla
        if params["searchField"]
          union = ""
          n_where, n_param = parse_params(params["searchField"], params[:searchOper], params[:searchString])
        else
          n_where, n_param = get_condiciones_sencillas(params)
        end
        where << n_where
        parametros  = parametros + n_param
      end #if complejo?

      condiciones = [where.join(" #{union} ")]
      condiciones += parametros
    end #if buscar?
    registros = clase.find(:all,
      tipo => incluir, :order => sortname+' '+sortorder,
      :limit =>rp, :offset =>start, :conditions=>condiciones )
    count = clase.count(:all,
      :joins => incluir, :conditions=>condiciones)
    return registros,count
  end

  #Convierte los operadores jqGrid ne, etc a los SQLs correspondientes
  def parse_params(field, oper, value)
    case oper
    when "eq"
      condiciones = [field +" = ?", value]
    when "lt"
      condiciones = [field +" < ?", value]
    when "le"
      condiciones = [field +" <= ?", value]
    when "gt"
      condiciones = [field +" > ?", value]
    when "ge"
      condiciones = [field +" >= ?", value]
    when "ne"
      condiciones = [field +" <> ?", value]
    when "bn"
      condiciones = ["not " + field +" like ?", "#{value}%"]
    when "bw"
      condiciones = [field +" like ?", "#{value}%"]
    when "ew"
      condiciones = [field +" like ?", "%#{value}"]
    when "cn"
      condiciones = [field +" like ?", "%#{value}%"]
    else
      condiciones = []
    end
    return condiciones
  end

  def get_condiciones_sencillas(params)
    comunes = ["_search", "rows", "page", "sidx", "sord", "controller", "action", "nd","filters"]
    opts = params.reject {|key,val| comunes.include?(key.to_s)}
    o_where = []
    n_param = []
    opts.each do |key,val|
      next if val.empty?
      o_where << (val.include?('null') ? "#{key} is #{val}" : "#{key} = ?")
      n_param << val.to_s
    end
    n_param.empty? ? ["",[]] : [o_where.join(" AND "),n_param]
  end
end
